using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Driver;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.Entities;
using Sustainalytics.MongoDB.Extensions;
using Sustainalytics.Synchronization.Validation.Entities.CorporateGovernance;
using Sustainalytics.Synchronization.Validation.Handlers.Common;
using Sustainalytics.Synchronization.Validation.Handlers.CorporateGovernance;
using Sustainalytics.Synchronization.Validation.Internals;
using Sustainalytics.Synchronization.Validation.ValidationRules.CorporateGovernance;
using Sustainalytics.Synchronization.Validation.Validators;
using Xunit;
using Xunit.Abstractions;

namespace Sustainalytics.Synchronization.Validation.Tests.IntegrationTest
{
    public class GovernanceMissingScoresRule_IntegrationTest
    {
        private const string MongodbGovernanceConnectionString = "mongodb://54.72.160.155:27017/GovernanceDW_B";

        private const string MongodbClientConnectionString = "mongodb://54.72.160.155:27017/ClientDW_B";

        private readonly GovernanceMissingScoresRule _sut;
        private readonly CorporateGovernanceCompanies companies = new CorporateGovernanceCompanies();
        private readonly WhiteListCompanies whiteListCompanies = new WhiteListCompanies();
        private readonly IMongoCollection<CorporateData> corporateMongoCollection = MongoFactory.GetCollectionFromDatabase<CorporateData>(MongodbClientConnectionString);

        private readonly IMongoCollection<GovernanceIndicator> governanceIndicatorsCollection =
            MongoFactory.GetCollectionFromDatabase<GovernanceIndicator>(MongodbGovernanceConnectionString);

        private readonly IMongoCollection<GovernanceCompanyProfile> governanceProfileCollection =
            MongoFactory.GetCollectionFromDatabase<GovernanceCompanyProfile>(MongodbGovernanceConnectionString);

        private readonly ITestOutputHelper output;

        public GovernanceMissingScoresRule_IntegrationTest(ITestOutputHelper output)
        {
            this.output = output;

            var indicatorCollection =
                MongoFactory.GetCollectionFromDatabase<GovernanceIndicatorTemplate>(MongodbGovernanceConnectionString);
            var indicatorHashSet = new IndicatorsHashSet();
            var indicatorLoader = new IndicatorsTemplateHashSetLoader(indicatorCollection, indicatorHashSet);
            indicatorLoader.LoadAsync().Wait();
            var corporateDataLoader = new GovernanceCorporateDataLoader(corporateMongoCollection, companies, whiteListCompanies);
            corporateDataLoader.LoadAsync().Wait();

            _sut = new GovernanceMissingScoresRule();
            _sut.SetDependency(indicatorHashSet);
        }

        [Fact]
        public async Task TestHandler()
        {
            var indicatorCollections = new ValidationMongoCollection<GovernanceIndicator>
                                    {
                                        OldCollection =
                                            governanceIndicatorsCollection,
                                        CurrentCollection =
                                            governanceIndicatorsCollection
                                    };
            var issueCollection = new ValidationMongoCollection<GovernanceIssue>
                                    {
                                        OldCollection = MongoFactory.GetCollectionFromDatabase<GovernanceIssue>(MongodbGovernanceConnectionString),
                                        CurrentCollection = MongoFactory.GetCollectionFromDatabase<GovernanceIssue>(MongodbGovernanceConnectionString)
                                    };

            var handler = new GovernanceProfileHandler(
                governanceProfileCollection,
                new IndicatorHandler(indicatorCollections),
                new GovernanceIssuesHandler(issueCollection),
                new Validator<GovernanceValidationProfile>(new[] { _sut }),
                companies);

            var isInvalid = new List<Guid>();
            await handler.ForEachElementsAsync((result) =>
                {
                    if (!result.IsValid)
                    {
                        isInvalid.AddRange(result.ValidationErrors.Select(x => x.Key));
                    }
                }).ConfigureAwait(false);

            foreach (var item in isInvalid)
            {
                output.WriteLine(item.ToString());
            }

            Assert.NotEmpty(isInvalid);
        }

        [Fact]
        public async Task TestMethod()
        {
            var isInvalid = new List<Guid>();
            await governanceProfileCollection.Find(Builders<GovernanceCompanyProfile>.Filter.Empty).ForEachAsync(
                async (item)
                =>
                    {
                        var governanceProfile = new GovernanceValidationProfile
                        {
                            CompanyId = item.Id,
                            GovernanceIndicators = await governanceIndicatorsCollection
                                                            .Find(Builders<GovernanceIndicator>.Filter.Where(x => x.CompanyId == item.Id))
                                                            .ToListAsync()
                                                            .ConfigureAwait(false)
                        };
                        var result = _sut.IsValid(governanceProfile, null);
                        if (!result)
                        {
                            isInvalid.Add(item.Id);
                        }
                    }).ConfigureAwait(false);
            foreach (var item in isInvalid)
            {
                output.WriteLine(item.ToString());
            }

            Assert.NotEmpty(isInvalid);
        }
    }
}